package _case

import (
	"fmt"
	"sync"
	"time"
)

func CondCase() {
	list := make([]int, 0)
	cond := sync.NewCond(&sync.Mutex{})

	go readList(&list, cond)
	go readList(&list, cond)
	go readList(&list, cond)
	time.Sleep(time.Second)
	initList(&list, cond)
}

func initList(list *[]int, c *sync.Cond) {
	//主叫方，可以持有锁，也可以不持锁
	c.L.Lock()
	defer c.L.Unlock()
	for i := 0; i < 10; i++ {
		*list = append(*list, i)
	}
	//唤醒所有等待的协程
	c.Broadcast()
	//唤醒其中一个
	//c.Signal()
}

func readList(list *[]int, c *sync.Cond) {
	//被叫方，必须持锁
	c.L.Lock()
	defer c.L.Unlock()
	for len(*list) == 0 {
		fmt.Println("readlist wait")
		c.Wait()
	}
	fmt.Println("list数据为：", *list)
}

type queue struct {
	list []int
	cond *sync.Cond
}

func newQueue() *queue {
	q := queue{
		list: make([]int, 0),
		cond: sync.NewCond(&sync.Mutex{}),
	}
	return &q
}

func (q *queue) Put(v int) {
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	q.list = append(q.list, v)
	// 当数据写入成功，唤醒一个协程处理数据
	q.cond.Signal()
}

func (q *queue) GetMany(n int) []int {
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	for len(q.list) < n {
		q.cond.Wait()
	}
	list := q.list[:n]
	q.list = q.list[n:]
	return list
}

func CondQueueCase() {
	q := newQueue()
	var wg sync.WaitGroup
	for i := 1; i < 10; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			list := q.GetMany(i)
			fmt.Printf("%d:%d \n", i, list)
		}(i)
	}

	for i := 0; i < 100; i++ {
		q.Put(i)
	}

	wg.Wait()
}

//func CondCase() {
//	list := make([]int, 0)
//	list = append(list, 1, 2, 3, 4)
//	fmt.Printf("%p\n", list)
//	fmt.Printf("%p\n", &list)
//	fmt.Println("===========================================")
//	initList(list)
//	fmt.Println("===========================================")
//	fmt.Println(list)
//	fmt.Printf("%p\n", list)
//	fmt.Printf("%p\n", &list)
//}
//// 不传递指针，会导致append产生新切片
//func initList(list []int) {
//	fmt.Printf("%p\n", list)
//	fmt.Printf("%p\n", &list)
//	list[2] = 10
//	// 改变值不影响原来的切片，而是一个新的切片
//	list = append(list, 20)
//	fmt.Printf("%p\n", list)
//	fmt.Printf("%p\n", &list)
//	fmt.Println(list)
//}
